home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / bash / bash-108 / bash-108.zoo / bash-1.08 / nojobs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-22  |  8.0 KB  |  358 lines

  1. /* The thing that makes children, remembers them, and contains wait loops. */
  2.  
  3. /* This file works under BSD, System V, minix, and Posix systems. */
  4.  
  5. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  6.  
  7. This file is part of GNU Bash, the Bourne Again SHell.
  8.  
  9. Bash is free software; you can redistribute it and/or modify it under
  10. the terms of the GNU General Public License as published by the Free
  11. Software Foundation; either version 1, or (at your option) any later
  12. version.
  13.  
  14. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  15. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17. for more details.
  18.  
  19. You should have received a copy of the GNU General Public License along
  20. with Bash; see the file COPYING.  If not, write to the Free Software
  21. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <fcntl.h>
  26. #include <signal.h>
  27. #include <setjmp.h>
  28. #include <errno.h>
  29.  
  30. #include "config.h"
  31. #include "general.h"
  32. #include "jobs.h"
  33.  
  34. #if !defined (USG) && !defined (_POSIX_VERSION)
  35. #  include <sgtty.h>
  36. #else
  37. #  if defined (USG)
  38. #    include <termio.h>
  39. #    include <sys/ttold.h>
  40. #  else 
  41. #    include <termios.h>
  42. #  endif
  43. #endif /* !USG && !_POSIX_VERSION */
  44.  
  45. #ifndef SIGABRT
  46. #define SIGABRT SIGIOT
  47. #endif
  48.  
  49. #if defined (USG) || defined (_POSIX_VERSION)
  50. #define killpg(pg, sig)        kill(-(pg),(sig))
  51. #endif
  52.  
  53. #if defined (USG)
  54. #define siginterrupt(sig, code)
  55. #endif
  56.  
  57. pid_t last_made_pid = (pid_t)-1;
  58. pid_t last_asynchronous_pid = (pid_t)-1;
  59.  
  60. extern int errno;
  61.  
  62. /* Initialize the job control mechanism, and set up the tty stuff. */
  63. initialize_jobs ()
  64. {
  65.   get_tty_state ();
  66. }
  67.  
  68. /* Setup this shell to handle C-C, etc. */
  69. initialize_job_signals ()
  70. {
  71.   extern int login_shell;
  72.   extern sighandler sigint_sighandler ();
  73.  
  74.   signal (SIGINT, sigint_sighandler);
  75.   signal (SIGQUIT, SIG_IGN);
  76.  
  77.   /* If this is a login shell we don't wish to be disturbed by
  78.      stop signals. */
  79.   if (login_shell)
  80.     {
  81. #ifdef SIGTSTP
  82.       signal (SIGTSTP, SIG_IGN);
  83.       signal (SIGTTOU, SIG_IGN);
  84.       signal (SIGTTIN, SIG_IGN);
  85. #endif
  86.     }
  87. }
  88.  
  89. /* Fork, handling errors.  Returns the pid of the newly made child, or 0.
  90.    COMMAND is just for remembering the name of the command; we don't do
  91.    anything else with it.  ASYNC_P says what to do with the tty.  If
  92.    non-zero, then don't give it away. */
  93. pid_t
  94. make_child (command, async_p)
  95.      char *command;
  96.      int async_p;
  97. {
  98.   pid_t pid;
  99.  
  100.   /* Discard saved memory. */
  101.   if (command)  
  102.     free (command);
  103.  
  104.   /* Make new environment array if neccessary. */
  105.   maybe_make_export_env ();
  106.  
  107.   /* Create the child, handle severe errors. */
  108.   if ((pid = fork ()) < 0)
  109.     {
  110.       report_error ("fork: %s", strerror (errno));
  111.  
  112.       throw_to_top_level ();
  113.     }
  114.  
  115.   if (!pid)
  116.     {
  117.       /* Ignore INT, HUP, and QUIT in asynchronous children. */
  118.       if (async_p)
  119.     {
  120.       signal (SIGINT, SIG_IGN);
  121.       signal (SIGQUIT, SIG_IGN);
  122.       signal (SIGHUP, SIG_IGN);
  123.       last_asynchronous_pid = getpid ();
  124.     }
  125.       else
  126.     {
  127.       restore_default_signal (SIGINT);
  128.       restore_default_signal (SIGQUIT);
  129.  
  130. #if defined (SIGTSTP)
  131.       signal (SIGTSTP, SIG_DFL);
  132.       signal (SIGTTIN, SIG_DFL);
  133.       signal (SIGTTOU, SIG_DFL);
  134. #endif
  135.  
  136.       restore_original_signals ();     /* Cancel traps, in trap.c. */
  137.     }
  138.  
  139.       /* Children are easily terminated with SIGTERM. */
  140.       restore_default_signal (SIGTERM);
  141.     }
  142.   else
  143.     {
  144.       /* In the parent. */
  145.       last_made_pid = pid;
  146.  
  147.       if (async_p)
  148.     last_asynchronous_pid = pid;
  149.     }
  150.   return (pid);
  151. }
  152.  
  153. /* Wait for a single pid (PID) and return its exit status. */
  154. wait_for_single_pid (pid)
  155.      pid_t pid;
  156. {
  157.   pid_t got_pid;
  158.   WAIT status;
  159.  
  160.   siginterrupt (SIGINT, 1);
  161.   while ((got_pid = wait (&status)) != pid)
  162.     {
  163.       if (got_pid < 0)
  164.     {
  165.       if (errno != EINTR && errno != ECHILD)
  166.         {
  167.           siginterrupt (SIGINT, 0);
  168.           file_error ("wait");
  169.         }
  170.       break;
  171.     }
  172.     }
  173.   siginterrupt (SIGINT, 0);
  174.   QUIT;
  175. }
  176.  
  177. /* Wait for all of the shell's children to exit. */
  178. wait_for_background_pids ()
  179. {
  180.   /* If we aren't using job control, we let the kernel take care of the
  181.      bookkeeping for us.  wait () will return -1 and set errno to ECHILD 
  182.      when there are no more unwaited-for child processes on both
  183.      4.2 BSD-based and System V-based systems. */
  184.  
  185.   siginterrupt (SIGINT, 1);
  186.   while (1)
  187.     {
  188.       pid_t got_pid;
  189.       WAIT status;
  190.  
  191.       while ((got_pid = wait(&status)) != -1)  /* wait for ECHILD */
  192.     ;
  193.       if (errno != EINTR && errno != ECHILD)
  194.     {
  195.       siginterrupt (SIGINT, 0);
  196.       file_error("wait");
  197.     }
  198.       break;
  199.     }
  200.   siginterrupt (SIGINT, 0);
  201.   QUIT;
  202. }
  203.  
  204. /* Wait for pid (one of our children) to terminate. */
  205. int
  206. wait_for (pid)
  207.      pid_t pid;
  208. {
  209.   extern int interactive;
  210.   int return_val;
  211.   pid_t got_pid;
  212.   WAIT status;
  213.  
  214.   /* Make sure that the process we are waiting for is valid. */
  215.   if ((kill (pid, 0) < 0) && (errno == ESRCH))
  216.     return (0);
  217.  
  218.   siginterrupt (SIGINT, 1);
  219.   while ((got_pid = wait (&status)) != pid)
  220.     {
  221.       if (got_pid < 0 && errno == ECHILD)
  222.     {
  223. #if !defined (_POSIX_VERSION)
  224.       status.w_termsig = status.w_retcode = 0;
  225. #else
  226.       status = 0;
  227. #endif /* _POSIX_VERSION */
  228.       break;
  229.     }
  230.       else if (got_pid < 0 && errno != EINTR)
  231.     programming_error ("got errno %d while waiting for %d", errno, pid);
  232.     }
  233.   siginterrupt (SIGINT, 0);
  234.  
  235. #if 0
  236.   /* Not needed because the builtin wait does not go through this path. */
  237.   if (interactive)    /* allow the user to ^C out of the builtin wait */
  238.     QUIT;
  239. #endif
  240.  
  241.   /* Default return value. */
  242.   /* ``a full 8 bits of status is returned'' */
  243.   if (WIFSIGNALED (status))
  244.     return_val = 128 + WTERMSIG (status);
  245.   else
  246.     return_val = WEXITSTATUS (status);
  247.                             
  248.   if (!WIFSTOPPED (status) && WIFSIGNALED (status) &&
  249.       (WTERMSIG (status) != SIGINT))
  250.     {
  251.       extern char *sys_siglist[];
  252.       fprintf (stderr, "%s", sys_siglist[WTERMSIG (status)]);
  253.       if (WIFCORED (status))
  254.     fprintf (stderr, " (core dumped)");
  255.       fprintf (stderr, "\n");
  256.     }
  257.  
  258.   if (WIFSIGNALED (status) || WIFSTOPPED (status))
  259.     set_tty_state ();
  260.   else
  261.     get_tty_state ();
  262.                             
  263.   return (return_val);
  264. }
  265.  
  266. /* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
  267.    If PID does belong to a job, and the job is stopped, then CONTinue the
  268.    job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
  269.    then kill the process group associated with PID. */
  270. int
  271. kill_pid (pid, signal, group)
  272.      pid_t pid;
  273.      int signal, group;
  274. {
  275.   int result;
  276.  
  277.   if (group)
  278.     result = killpg (pid, signal);
  279.   else
  280.     result = kill (pid, signal);
  281.  
  282.   return (result);
  283. }
  284.  
  285. #if defined (_POSIX_VERSION)
  286. static struct termios shell_tty_info;
  287. #else
  288. #  if defined (USG)
  289. static struct termio shell_tty_info;
  290. #  else
  291. static struct sgttyb shell_tty_info;
  292. #  endif /* USG */
  293. #endif /* _POSIX_VERSION */
  294.  
  295. static int got_tty_state = 0;
  296.  
  297. /* Fill the contents of shell_tty_info with the current tty info. */
  298. get_tty_state ()
  299. {
  300.   int tty = open ("/dev/tty", O_RDONLY);
  301.   if (tty != -1)
  302.     {
  303.    
  304. #if defined (_POSIX_VERSION)
  305.       tcgetattr (tty, &shell_tty_info);
  306. #else
  307. #  if defined (USG)
  308.       ioctl (tty, TCGETA, &shell_tty_info);
  309. #  else
  310.       ioctl (tty, TIOCGETP, &shell_tty_info);
  311. #  endif
  312. #endif
  313.       close (tty);
  314.       got_tty_state = 1;
  315.     }
  316. }
  317.  
  318. /* Make the current tty use the state in shell_tty_info. */
  319. set_tty_state ()
  320. {
  321.   int tty = open ("/dev/tty", O_RDONLY);
  322.   if (tty != -1)
  323.     {
  324.       if (!got_tty_state)
  325.         return;
  326. #if defined (_POSIX_VERSION)
  327.       tcsetattr (tty, TCSADRAIN, &shell_tty_info);
  328. #else
  329. #  if defined (USG)
  330.       ioctl (tty, TCSETAW, &shell_tty_info);  /* Wait for output, no flush */
  331. #  else
  332.       ioctl (tty, TIOCSETN, &shell_tty_info);
  333. #  endif
  334. #endif
  335.       close (tty);
  336.     }
  337. }
  338.  
  339. /* Give the terminal to PGRP.  */
  340. give_terminal_to (pgrp)
  341.      pid_t pgrp;
  342. {
  343. }
  344.  
  345. /* Stop a pipeline. */
  346. stop_pipeline (async, ignore)
  347.      int async;
  348.      char *ignore;
  349. {
  350. }
  351.  
  352. /* Print descriptive information about the job with leader pid PID. */
  353. describe_pid (pid)
  354.      pid_t pid;
  355. {
  356.   fprintf (stderr, "<%d>\n", (int) pid);
  357. }
  358.